package org.tweego.items 
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	import org.goasap.events.GoEvent;
	import org.goasap.items.LinearGo;
	import org.tweego.TweegoProperties;
	import org.tweego.events.TweegoEvent;	

	/**
	 * @author Sebastian Weyrauch
	 */
	public class TweegoItem extends LinearGo
	{
		public var target:*;

		protected var tweenProperties:Object;
		protected var startProperties:Object;
		protected var changeProperties:Object;
		
		public function TweegoItem(action:Object)
		{
			super();
			//
			tweenProperties = {};
			for(var property:String in action) tweenProperties[property] = action[property];
			startProperties = {};
			changeProperties = {};
			//
			init();
		}
		
		override public function start():Boolean 
		{	
			checkForStartProperties();
			//
			for(var prop:String in tweenProperties)
			{
				startProperties[prop] = target[prop] || 0;					
				changeProperties[prop] = useRelative?tweenProperties[prop]:(tweenProperties[prop]-startProperties[prop]);
			}

			return (super.start());
		}
		
		override public function dispatchEvent(e:Event):Boolean
		{
			var tweegoEvent:TweegoEvent = new TweegoEvent(e.type, e.bubbles, e.cancelable);
			return super.dispatchEvent(tweegoEvent);
		}

		override protected function onUpdate(type:String):void 
		{
			for(var property:String in tweenProperties)
			{
				updateProperty(property);
			}
		}
		
		protected function updateProperty(property:String):void
		{
			var value:Number = super.correctValue(startProperties[property]+changeProperties[property]*_position);
			if(isNaN(value)) return;
			//
			target[property] = value;
		}
		
		protected function checkForStartProperties():void
		{
			for(var prop:String in tweenProperties)
			{
				var parts:Array = prop.split("_");
				if(parts.length==1) continue;
				
				var newProp:String = parts[1];
				
				if(!Object(target).hasOwnProperty(newProp)) continue;
				
				switch(parts[0])
				{
					case "start":
						target[newProp] = tweenProperties[prop];
						delete tweenProperties[prop];
						break;
					case "from":
						tweenProperties[newProp] = tweenProperties[newProp] || target[newProp];
						target[newProp] = tweenProperties[prop];
						delete tweenProperties[prop];
						break;
				}
			}
		}
		
		protected function getValueForDefaultProperties(property:*):*
		{
			if(property is String)
			{
				return tweenProperties[property];
			}
			else if(property is Array)
			{
				var propertyList:Array = property as Array;
				for(var i:int = 0; i<propertyList.length; i++)
				{
					var value:* = tweenProperties[propertyList[i]];
					if(value!=null)
					{
						return value;
					}
				}
			}
			
			return null;
		}
				
		private function init():void
		{
			initDefaultProperties();
			//
			var durationIfEmpty:Number = getValueForDefaultProperties(TweegoProperties.DURATION) || 0;
			
			// Remove all default properties from the list
			var notTweenablePropertyList:Array = TweegoProperties.DEFAULT_PROPERTY_LIST;
			for(var i:int = 0; i<notTweenablePropertyList.length; i++)
			{
				delete tweenProperties[notTweenablePropertyList[i]];
			}
			
			// Check if there are any tweenable properties
			var empty:Boolean = true;
			for(var property:String in tweenProperties)
			{
				empty = false;
				break;
			}	
			if(empty)
			{
				duration = durationIfEmpty;
			}
		}
		
		private function initDefaultProperties():void
		{
			target = getValueForDefaultProperties(TweegoProperties.TARGET);			
			playableID = getValueForDefaultProperties(TweegoProperties.ID) || playableID;
			
			delay = getValueForDefaultProperties(TweegoProperties.DELAY) as Number || delay;
			duration = getValueForDefaultProperties(TweegoProperties.DURATION) as Number || duration;
			useRounding = getValueForDefaultProperties(TweegoProperties.USE_ROUNDING) as Boolean || useRounding;
			useRelative = getValueForDefaultProperties(TweegoProperties.USE_RELATIVE) as Boolean || useRelative;
			pulseInterval = getValueForDefaultProperties(TweegoProperties.PULSE_INTERVAL) as int || pulseInterval;
			useFrames = getValueForDefaultProperties(TweegoProperties.USE_FRAMES) as Boolean || useFrames;
			
			// Easing function
			var ease:Function = getValueForDefaultProperties(TweegoProperties.EASING) as Function;
			if(ease!=null) easing = ease;
						
			// Extra easing params
			var extra:Array = getValueForDefaultProperties(TweegoProperties.EXTRA_ARGS) as Array;
			if(extra==null && getValueForDefaultProperties(TweegoProperties.EXTRA1)) extra = [getValueForDefaultProperties(TweegoProperties.EXTRA1), getValueForDefaultProperties(TweegoProperties.EXTRA2)];
			extraEasingParams = extra || extraEasingParams;
			
			// Cycles
			repeater.cycles = getValueForDefaultProperties(TweegoProperties.CYCLES) as Number || repeater.cycles;
			var easeOnCycle:Function = getValueForDefaultProperties(TweegoProperties.EASING_ON_CYCLE) as Function;
			if(easeOnCycle!=null) repeater.easingOnCycle = easeOnCycle;
			repeater.reverseOnCycle = getValueForDefaultProperties(TweegoProperties.REVERSE_ON_CYCLE) as Boolean || repeater.reverseOnCycle;
			
			// Callback functions
			initCallbackFunctions();
		}
		
		private function initCallbackFunctions():void
		{
			var onStartFunc:Function = getValueForDefaultProperties(TweegoProperties.START_EVENT) as Function;
			if(onStartFunc!=null) addEventListener(GoEvent.START, onStartFunc, false, 0, true);
			
			var onStopFunc:Function = getValueForDefaultProperties(TweegoProperties.STOP_EVENT) as Function;
			if(onStopFunc!=null) addEventListener(GoEvent.STOP, onStopFunc, false, 0, true);
			
			var onPauseFunc:Function = getValueForDefaultProperties(TweegoProperties.PAUSE_EVENT) as Function;
			if(onPauseFunc!=null) addEventListener(GoEvent.PAUSE, onPauseFunc, false, 0, true);
			
			var onResumeFunc:Function = getValueForDefaultProperties(TweegoProperties.RESUME_EVENT) as Function;
			if(onResumeFunc!=null) addEventListener(GoEvent.RESUME, onResumeFunc, false, 0, true);
			
			var onUpdateFunc:Function = getValueForDefaultProperties(TweegoProperties.UPDATE_EVENT) as Function;
			if(onUpdateFunc!=null) addEventListener(GoEvent.UPDATE, onUpdateFunc, false, 0, true);
			
			var onCompleteFunc:Function = getValueForDefaultProperties(TweegoProperties.COMPLETE_EVENT) as Function;
			if(onCompleteFunc!=null) addEventListener(GoEvent.COMPLETE, onCompleteFunc, false, 0, true);
			
			var onCycleFunc:Function = getValueForDefaultProperties(TweegoProperties.CYCLE_EVENT) as Function;
			if(onCycleFunc!=null) addEventListener(GoEvent.CYCLE, onCycleFunc, false, 0, true);
		}
	}
}
